using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
using Microsoft.BizTalk.Component.Interop;
using Microsoft.BizTalk.TransportProxy.Interop;

namespace Microsoft.Samples.BizTalk.Adapter.Tcp.Receive
{
    /// <summary>
    ///     This class implements a receive adapter in BizTalk.
    /// </summary>
    /// <author>
    ///     Paul Brown
    /// </author>
    public partial class ReceiveAdapter : IBaseComponent,
                                          IBTTransport,
                                          IPersistPropertyBag,
                                          IBTTransportControl,
                                          IBTTransportConfig,
                                          IAdapter
    {
        #region IBTTransportConfig Members

        /// <summary>
        ///     This method is called whenever a new receive location is added to the adapter.
        /// </summary>
        public void AddReceiveEndpoint(string url, IPropertyBag adapterConfig, IPropertyBag bizTalkConfig)
        {
            TraceHelper.WriteEntry(TraceLevel.Info, ResourceConstants.ReceiveLocationAdded, url, this.TransportType);

            // Load configuration to get a receive endpoint object
            ReceiveLocation receiveEndpoint = this.CreateReceiveLocation(url, adapterConfig, bizTalkConfig);

            // Add it to list of managed endpoints
            lock (this._endpointLock)
            {
                // Ensure that a listener doesn't already exist that is listening on the same port
                foreach (ReceiveLocation endpoint in this._endpoints.Values)
                {
                    if (endpoint.ListenPort == receiveEndpoint.ListenPort)
                    {
                        // Port is the same - this can't happen, throw error
                        Exception e = new Exception(TraceHelper.FormatEntry(ResourceConstants.ReceiveDuplicateListenPortFound, receiveEndpoint.Uri, receiveEndpoint.ListenPort, endpoint.Uri));
                        TraceHelper.WriteRawEntry(TraceLevel.Error, e.Message);
                        throw (e);
                    }
                }

                // Add it
                this._endpoints.Add(url, receiveEndpoint);
            }

            // Start listening
            receiveEndpoint.Start();
        }

        /// <summary>
        ///     This method is called whenever a receive location is removed from the adapter.
        /// </summary>
        public void RemoveReceiveEndpoint(string url)
        {
            TraceHelper.WriteEntry(TraceLevel.Info, ResourceConstants.ReceiveLocationRemoved, url, this.TransportType);

            ReceiveLocation receiveEndpoint = null;

            // Find existing endpoint
            lock (this._endpointLock)
            {
                if (this._endpoints.ContainsKey(url))
                {
                    // Get reference
                    receiveEndpoint = this._endpoints[url];

                    // Remove it
                    this._endpoints.Remove(url);
                }
            }

            // Terminate it
            if (receiveEndpoint != null)
            {
                receiveEndpoint.Stop();
            }
        }

        /// <summary>
        ///     This method is called whenever the properties for a receive location are updated.
        /// </summary>
        public void UpdateEndpointConfig(string url, IPropertyBag adapterConfig, IPropertyBag bizTalkConfig)
        {
            TraceHelper.WriteEntry(TraceLevel.Info, ResourceConstants.ReceiveLocationConfigUpdated, url);

            ReceiveLocation receiveEndpoint = null;

            // Find existing endpoint
            lock (this._endpointLock)
            {
                if (this._endpoints.ContainsKey(url))
                {
                    // Get reference
                    receiveEndpoint = this._endpoints[url];

                    // Remove it
                    this._endpoints.Remove(url);
                }
            }

            // Terminate it
            receiveEndpoint.Stop();

            // Create a new endpoint with the new configuration
            receiveEndpoint = this.CreateReceiveLocation(url, adapterConfig, bizTalkConfig);

            // Add it to list of managed endpoints
            lock (this._endpointLock)
            {
                this._endpoints.Add(url, receiveEndpoint);
            }

            // Start listening
            receiveEndpoint.Start();
        }

        #endregion
    }
}
